%{
#include <stdio.h>
#include <string.h>
#include "DBG.h"
#include "wuji.h"
#include "y.tab.h"

int
yywrap(void)
{
    return 1;
}

static void
increment_line_number(void)
{
    wj_get_current_interpreter()->current_line_number++;
}

%}
%start COMMENT STRING_LITERAL_STATE
%%
<INITIAL>"函数："		return FUNCTION;
<INITIAL>"如果："		return IF;
<INITIAL>"若是："		return ELSIF;
<INITIAL>"否则"			return ELSE;
<INITIAL>"循环："		return WHILE;
<INITIAL>"全局："       return GLOBAL_T;
<INITIAL>"返回"			return RETURN_T;
<INITIAL>"跳出"			return BREAK;
<INITIAL>"跳过"			return CONTINUE;
<INITIAL>"空"			return NULL_T;
<INITIAL>"真"			return TRUE_T;
<INITIAL>"假"			return FALSE_T;

<INITIAL>"逐个："		return FOREACH;
<INITIAL>"闭包："		return CLOSURE;

<INITIAL>"尝试"			return TRY;
<INITIAL>"异常"			return CATCH;
<INITIAL>"最后"			return FINALLY;

<INITIAL>"抛出"			return THROW;
<INITIAL>"最终"			return FINAL;

<INITIAL>"（"           return LP;
<INITIAL>"）"           return RP;
<INITIAL>"【"			return LB;
<INITIAL>"】"			return RB;
<INITIAL>"："           return COLON;
<INITIAL>"{"            return LC;
<INITIAL>"}"            return RC;
<INITIAL>"，"			return COMMA;
<INITIAL>"·"           return DOT;

<INITIAL>"&&"           return LOGICAL_AND;
<INITIAL>"||"           return LOGICAL_OR;
<INITIAL>"与"			return LOGICAL_AND;
<INITIAL>"或"			return LOGICAL_OR;


<INITIAL>"="            return ASSIGN;
<INITIAL>"取值"         return ASSIGN;

<INITIAL>"=="           return EQ;
<INITIAL>"!="           return NE;
<INITIAL>">"            return GT;
<INITIAL>">="           return GE;
<INITIAL>"<"            return LT;
<INITIAL>"<="           return LE;
<INITIAL>"等于"         return EQ;
<INITIAL>"不等于"       return NE;
<INITIAL>"大于"         return GT;
<INITIAL>"大于等于"     return GE;
<INITIAL>"小于"         return LT;
<INITIAL>"小于等于"     return LE;

<INITIAL>"+"            return ADD;
<INITIAL>"-"            return SUB;
<INITIAL>"*"            return MUL;
<INITIAL>"/"            return DIV;
<INITIAL>"%"            return MOD;
<INITIAL>"!"            return EXCLAMATION;
<INITIAL>"加"           return ADD;
<INITIAL>"减"           return SUB;
<INITIAL>"乘"           return MUL;
<INITIAL>"除"           return DIV;
<INITIAL>"求余"         return MOD;
<INITIAL>"取反"         return EXCLAMATION;


<INITIAL>"+="           return ADD_ASSIGN_T;
<INITIAL>"-="           return SUB_ASSIGN_T;
<INITIAL>"*="           return MUL_ASSIGN_T;
<INITIAL>"/="           return DIV_ASSIGN_T;
<INITIAL>"%="           return MOD_ASSIGN_T;
<INITIAL>"++"           return INCREMENT;
<INITIAL>"--"           return DECREMENT;

<INITIAL>[A-Za-z_][A-Za-z_0-9]* {
	/* 普通C语言标识符 */
    yylval.identifier = wj_create_identifier(yytext);
    return IDENTIFIER;
}
<INITIAL>[A-Za-z_]*([\xe4-\xe9][\x80-\xbf]*)* {
	/* 识别中文标识符 */
	/* printf("%s\n", yytext); */
    yylval.identifier = wj_create_identifier(yytext);
    return IDENTIFIER;
}
<INITIAL>([1-9][0-9]*)|"0" {
	/* 整数 */
    Expression  *expression = wj_alloc_expression(INT_EXPRESSION);
    sscanf(yytext, "%d", &expression->u.int_value);
    yylval.expression = expression;
    return INT_LITERAL;
}
<INITIAL>[0-9]+\.[0-9]+ {
	/* 浮点数 */
    Expression  *expression = wj_alloc_expression(DOUBLE_EXPRESSION);
    sscanf(yytext, "%lf", &expression->u.double_value);
    yylval.expression = expression;
    return DOUBLE_LITERAL;
}
<INITIAL>"“"|"”" {
    wj_open_string_literal();
    BEGIN STRING_LITERAL_STATE;
}
<INITIAL>^[\t]* {
	/* 匹配行首的tab键 */
	/* 后期用于尝试使用缩进作为代码块 */
}
<INITIAL>[ \t] ;
<INITIAL>\n {increment_line_number();}
<INITIAL>#     BEGIN COMMENT;
<INITIAL>.      {
	/* 非法字符并报错 */
    char buf[LINE_BUF_SIZE];

    if (isprint(yytext[0])) {
        buf[0] = yytext[0];
        buf[1] = '\0';
    } else {
        sprintf(buf, "0x%02x", (unsigned char)yytext[0]);
    }

    wj_compile_error(CHARACTER_INVALID_ERR,
                      STRING_MESSAGE_ARGUMENT, "bad_char", buf,
                      MESSAGE_ARGUMENT_END);
}
<COMMENT>\n     {
    increment_line_number();
    BEGIN INITIAL;
}
<COMMENT>.      ;
<STRING_LITERAL_STATE>"“"|"”"        {
    Expression *expression = wj_alloc_expression(STRING_EXPRESSION);
    expression->u.string_value = wj_close_string_literal();
    yylval.expression = expression;
    BEGIN INITIAL;
    return STRING_LITERAL;
}
<STRING_LITERAL_STATE>\n        {
    wj_add_string_literal('\n');
    increment_line_number();
}
<STRING_LITERAL_STATE>\\\"      wj_add_string_literal('"');
<STRING_LITERAL_STATE>\\n       wj_add_string_literal('\n');
<STRING_LITERAL_STATE>\\t       wj_add_string_literal('\t');
<STRING_LITERAL_STATE>\\\\      wj_add_string_literal('\\');
<STRING_LITERAL_STATE>.         wj_add_string_literal(yytext[0]);
%%
